perf(bp): collapse aggregated verifier into single vendored MSM#104
Open
tesseract-ripple wants to merge 2 commits into
Open
perf(bp): collapse aggregated verifier into single vendored MSM#104tesseract-ripple wants to merge 2 commits into
tesseract-ripple wants to merge 2 commits into
Conversation
Self-contained vendor of secp256k1_ecmult_multi_var (Pippenger/Straus MSM) from libsecp256k1 v0.7.1, supporting the upcoming *_verify_batch API for compact-sigma + aggregated-BP batch verification. Vendor layout (third_party/secp256k1-msm/) ------------------------------------------ - 39 .h files + precomputed_ecmult.c (~2.3 MB of generator table data) copied from libsecp256k1 src/ at tag v0.7.1, commit 1a53f4961f337b4d166c25fce72ef0dc88806618. See PROVENANCE. - mpt_msm.c: single wrapper translation unit that includes the vendored headers and exposes the one external API symbol, mpt_msm_variable_time. All upstream functions are file-static; no link-time collision with the still-linked libsecp256k1. - Two compile-time -D renames (-Dsecp256k1_pre_g=mpt_secp256k1_pre_g and the _128 variant) to namespace the only non-static data symbols (the generator precomputation tables, which the linked libsecp256k1 also exports). - Local edit to util.h: relative include "../include/secp256k1.h" changed to <secp256k1.h> so it resolves through the linked install. Only edit to upstream sources. Self-containment ---------------- The vendor includes dependent internal types (secp256k1_gej, secp256k1_scalar, secp256k1_fe, scratch-space layouts), not just ecmult_impl.h and the WNAF helpers. This decouples the vendored MSM's correctness from the linked libsecp256k1 binary's version, so this PR does NOT change the existing libsecp256k1 Conan pin. Threat model ------------ mpt_msm_variable_time is variable-time. Validator path (D4) only; the verifier has no secret inputs. The two-profile API shape (mpt_msm_variable_time vs the planned mpt_msm_constant_time -- see XRPLF#87) makes the constant-time requirement audit-visible at the call site. Build integration ----------------- - CMake OBJECT library mpt-crypto-msm-vendor; linked into mpt-crypto. - -Wno-pedantic only on the vendored TU; main library remains under -Wall -Wextra -Wpedantic -Werror. - .pre-commit-config.yaml: third_party/ excluded from style hooks so the vendored upstream files stay close to their upstream form (clean diffs on re-sync). Large-file limit raised to 4 MB to admit precomputed_ecmult.c. Tests ----- tests/test_mpt_msm.c: calibration test that compares the vendored MSM output to a reference computed via the public libsecp256k1 API (tweak_mul + pubkey_combine in a loop) on randomized inputs. Bit- identical match required across N_TRIALS. Confirms scalar/point encoding conventions, group-element layout, and end-to-end correctness of the vendoring. Drift detection --------------- None. We follow the same operational model as the Conan lockfile under conan/lockfile/ (XRPLF#95): pin known-good state, re-sync deliberately when there is a reason (security fix, performance gain). No automated tripwire -- same as for Conan-managed dependencies. Out of scope (tracked separately) --------------------------------- - mpt_msm_constant_time profile for the prover path: XRPLF#87. - *_verify_batch API for the four sigma proofs and aggregated BP: XRPLF#88. (Design in cmpt-ct-and-batch.tex.) - Lift the BP m in {1,2} aggregation restriction: XRPLF#46. - rippled-side integration. - Any change to the existing libsecp256k1 dep pin.
…RPLF#100) Collapse secp256k1_bulletproof_verify_agg's two equality checks (the range-relation LHS/RHS and the inner-product-collapsed P+IPA check) into one mpt_msm_variable_time call that must return the identity. Variable-time MSM dispatch via the vendored Pippenger/Straus ecmult landed in PR XRPLF#89 (mpt-crypto-msm-vendor); this PR consumes it. Equation. With a fresh Fiat-Shamir batching weight c (BBB+18-style random-linear-combination), the check E1 + c*E2 = 0 unrolls to a (2n + 2*log n + m + 6)-term MSM plus an optional G coefficient (t_hat - delta) passed via inp_g_sc_be32. The H_k coefficient absorbs the y^{-k} factor that was previously applied to a separately-built Hprime vector, and the per-term s_k product (the IPA fold weight) is computed inline matching fold_generators()'s G-fold pattern; s_k^{-1} matches the H-fold pattern, recomputed directly to avoid n scalar inversions. Soundness. c is bound to the entire proof (last IPA round challenge + tau_x + mu + a + b) via SHA-256 with the dedicated tag "MPT_BP_VERIFY_BATCH_RLC". A malicious prover that makes E1 and E2 individually non-zero would need to predict c before committing the proof; Schwartz-Zippel gives the standard 1/q bound. The c == 0 case (~1/2^256) is explicitly rejected to keep the soundness reasoning clean. Perf (Apple M-series, m=2, n=128, 5-iteration avg): before: 10.0 ms after: 1.68 ms speedup: ~6x This exceeds the 2-4x estimate in XRPLF#100; the extra factor comes from also folding the (m+4)-term range check and the rounds-many IPA folding mults into the same MSM, where the constant-fan-out terms contribute to the GLV/Pippenger amortisation. Other changes. * secp256k1_bulletproof_ipa_msm() is untouched; the prover's calculate_commitment_term() still routes through it. Verifier-only swap, prover CT contract preserved. The constant-time MSM profile for the prover is tracked separately in XRPLF#87. * Static helper ipa_verify_explicit() removed; tests/test_ipa.c carries its own copy of the round-by-round IPA-verify check. * fold_generators() and apply_ipa_folding_to_P() retained because tests/test_ipa.c still uses them. Tests. 11/11 ctest green (test_bulletproof_agg covers positive + negative paths for m in {1, 2} including v=0, v=1, v=UINT64_MAX, and the two tampered-commitment cases that exercise the rejection branch of the consolidated MSM).
2cd20ac to
403ae6a
Compare
This was referenced Jun 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #100. Stacked on #89 (vendored
mpt_msm_variable_time); thelast commit (
2cd20ac9) is the only #100 change. Review just thatcommit — the preceding commit is #89's vendor as already up for
review there.
What
Collapses
secp256k1_bulletproof_verify_agg's two equality checks(the range-relation
LHS == RHSand the inner-product-collapsedP + sum L,R == a*Gf + b*Hf + a*b*ux*U) into a singlempt_msm_variable_timecall that must return the identity.Equation
With a fresh Fiat–Shamir batching weight$c$ (BBB+18-style RLC), the$E_1 + c \cdot E_2 = 0$ unrolls to a
$(2n + 2 \log n + m + 6)$ -term MSM plus an optional $G$ coefficient
$t_{\hat{}} - \delta$ passed via $H_k$ coefficient$y^{-k}$ factor that the previous code applied via a$s_k$ product (the$s_k^{-1}$ matches the H-fold pattern, recomputed$n$ scalar inversions.
check
inp_g_sc_be32. Theabsorbs the
separately-built
Hprimevector. The per-termIPA fold weight) is computed inline matching
fold_generators()'sG-fold pattern;
directly to avoid
Soundness
u_{rounds-1}+tau_x+mu+a+b) via SHA-256 with the dedicated tagMPT_BP_VERIFY_BATCH_RLC. A malicious prover that makesthe proof; Schwartz–Zippel gives the standard
soundness reasoning clean.
Perf (Apple M-series, m=2, n=128, 5-iteration avg)
vendor-msm-pippengertip)Exceeds the 2–4× estimate in #100; the extra factor comes from also$(m+4)$ -term range check and the $\log n$ IPA folding
folding the
mults into the same MSM (where the constant-fan-out terms contribute
to the GLV/Pippenger amortisation).
Other changes
secp256k1_bulletproof_ipa_msmis untouched. The prover'scalculate_commitment_termstill routes through the per-term loop,preserving the prover CT contract. The constant-time MSM profile
for the prover is tracked separately in mpt_msm_constant_time: constant-time MSM profile for the prover path #87.
ipa_verify_explicitis removed;tests/test_ipa.ccarries its own copy of the round-by-round IPA verify check.
fold_generatorsandapply_ipa_folding_to_Pare retained becausetests/test_ipa.cstill calls them.Tests
11/11 ctest green.$m \in {1, 2}$ including $v = 0$ , $v = 1$ ,
$v = \text{UINT64_MAX}$ , and the two tampered-commitment cases that
test_bulletproof_aggexercises positive andnegative paths for
trigger the rejection branch of the consolidated MSM.
Out of scope (tracked separately)